# -*- encoding:utf-8 -*-
# __author__ = 'chenyongbing'
# __poject__ = 'ops_platform'
# __datetime__ = '2022/5/13'
# __name__ = 'handles.py'
from apps.resource.models import *
from apps.cicd.models import *
from utils.kubernetes_helper import KubeClient
# from utils.imagesync_helper import ImageSyncHelper
import os
import re
import datetime
from utils.acr_helper import AcrHelper
# from utils.gitlab_helper import GL
from apps.system.handles import get_config_by_group


from apps.cicd.tasks import workorder_auto_do_task
from apps.cicd import flows
from apps.cicd.cache import set_deployment_info_cache, get_deployment_info_cache, get_pod_info_cahce, set_pod_info_cahce, set_deployment_exists_cache, get_deployment_exists_cache

from .base import get_workorder_kube_and_namespace, get_kube_by_service_env, get_workorder_template
from utils.yaml_helper import YamlHelper
# Create your code here.





def get_yaml_template(object):
    template = object.template or object.project.template
    if not template:
        return ''
    return template.yaml


def get_kubeconfig_file(id, kubeconfig):
    from django.conf import settings
    if not os.path.exists(os.path.join(settings.BASE_DIR, '.kube')):
        os.mkdir(os.path.join(settings.BASE_DIR, '.kube'))
    kubefile = os.path.join(settings.BASE_DIR, '.kube/kubeconfig-{}'.format(id))
    if os.path.exists(kubefile):
        return kubefile
    with open(kubefile, 'w+', newline=os.linesep) as fr:
        fr.write(kubeconfig)
    return kubefile





## 根据order_type 获取 flow function
def get_flow_function_name(order_type='restart'):
    function_name = order_type.capitalize() + 'Flow'
    return function_name











def get_demandorder_kube_and_namespace(demandorder):
    data = {}
    business_id = demandorder.business_id
    env_id = demandorder.env_id
    business_setting = LobEnvSetting.objects.filter(env_id=env_id, service_id__isnull=True, project_id__isnull=True,
                                                    business_id=business_id).first()
    if business_setting:
        kube = business_setting.kube
        namespace = business_setting.namespace
        data = {
            'kubeid': kube.id,
            'kubeconfig': kube.kubeconfig,
            'namespace': namespace
        }
    return data


def get_workorder_pods(workorder):
    service_name = workorder.service.name

    kube = get_workorder_kube_and_namespace(workorder)
    kubeid = str(kube.get('kubeid'))
    kubeconfig = kube.get('kubeconfig')
    namespace = kube.get('namespace')
    datas = get_pod_info_cahce(kubeid, namespace)
    if not datas:
        datas = []
        kubecli = KubeClient(kubeid, kubeconfig)
        pods = kubecli.get_namespaced_pod_list(namespace)
        # pods = kubecli.get_namespaced_pod_list(namespace, service_name + '-deployment')
        # redeploy_timestamp =  get_deployment_redeploy_timestamp(name=service_name+'-deployment', namespace=namespace)
        # datas[env_code] = pods
        datas += pods
        set_pod_info_cahce(kubeid, namespace, datas)

    newdatas = [data for data in datas if re.search('{0}-[^-]+-[^-]+$'.format(service_name+'-deployment'), data.get('name', ''))]
    return newdatas


def get_workorder_repotags(workorder):
    service = workorder.service
    business_id = service.business.id

    lobsetting = LobEnvSetting.objects.filter(business_id=business_id, project_id=None, env_id=workorder.env_id).first()
    if not lobsetting:
        return []
    repoobj = lobsetting.repo
    repo_namespace = lobsetting.repo_namespace
    return get_repotags(repo=repoobj, repo_namespace_name=repo_namespace, repo_name=service.code)


def get_workorder_replicas(workorder):
    service_name = workorder.service.name
    current_env = workorder.env.code
    kube = get_workorder_kube_and_namespace(workorder)
    kubeid = str(kube.get('kubeid'))
    kubeconfig = kube.get('kubeconfig')
    namespace = kube.get('namespace')
    kubecli = KubeClient(kubeid, kubeconfig)
    replicas = kubecli.get_deployment_replicas(name=service_name + '-deployment', namespace=namespace)
    return replicas


def get_deployment_replicas(service_id, env_id):
    service = Service.objects.get(id=service_id)
    env = Environment.objects.get(id=env_id)
    kube, namespace = get_kube_by_service_env(service, env)

    # kube = get_workorder_kube_and_namespace(workorder)
    if not kube:
        return True
    kubeid = str(kube.id)
    kubeconfig = kube.kubeconfig

    service_name = service.name

    kubecli = KubeClient(kubeid, kubeconfig)
    replicas = kubecli.get_deployment_replicas(name=service_name + '-deployment', namespace=namespace)
    return replicas


#  通过service 、 env 获取相关配置
def get_lob_setting_key_by_service(service, env, key='git_merge'):
    project = service.project
    business = service.business
    value = None
    filterparams = [
        {'env_id': env.id, 'service_id': service.id},
        {'env_id': env.id, 'project_id': project.id, 'service_id__isnull': True},
        {'env_id': env.id, 'business_id': business.id, 'project_id__isnull': True, 'service_id__isnull': True}
    ]
    for filterparam in filterparams:
        lobsetting_obj = LobEnvSetting.objects.filter(**filterparam).first()
        if value != None:
            break
        if lobsetting_obj:
            value = value or getattr(lobsetting_obj, key)

    return value

def workorder_flow_function(workorder, username):
    '''工单流程方法'''
    flow_name = get_flow_function_name(order_type=workorder.order_type)
    git_merge = get_lob_setting_key_by_service(workorder.service, workorder.env, key='git_merge')
    func = getattr(flows, flow_name)(workorder=workorder, username=username, git_merge=git_merge)
    return func









def workorder_deployment_exists(workorder):
    service_name = workorder.service.code
    env_name = workorder.env.code

    exists = get_deployment_exists_cache(service_name, env_name)
    if exists:
        return True
    kube = get_workorder_kube_and_namespace(workorder)
    if not kube:
        return True
    kubeid = str(kube.get('kubeid'))
    kubeconfig = kube.get('kubeconfig')
    namespace = kube.get('namespace')
    kubecli = KubeClient(kubeid, kubeconfig)
    deploylist = kubecli.get_namespaced_kind_list('Deployment', namespace)
    for deploy in deploylist:
        sname = re.sub('-deployment', '', deploy)
        set_deployment_exists_cache(sname, env_name, 1)
        if sname == service_name:
            exists = True
    return exists















def get_repotags(repo, repo_namespace_name, repo_name, limit=3):
    data = []
    if repo.type == 'aliyun':
        access_key_id = repo.access_key_id
        access_key_secret = repo.access_key_secret
        instance_id = repo.instance

        acr = AcrHelper(access_key_id=access_key_id, access_key_secret=access_key_secret)

        data = acr.get_repo_tags(instance_id=instance_id, repo_namespace_name=repo_namespace_name, repo_name=repo_name,
                                 page_size=limit)

    elif repo.type == 'demo':
        data = [{'ImageCreate': 1657209650000, 'Tag': 'T1_e20eaf_202207080000_159'},
                {'ImageCreate': 1657207833000, 'Tag': 'T1_d0e61a_202207072329_158'},
                {'ImageCreate': 1657207157000, 'Tag': 'T1_d0a8fb_202207072318_157'},
                {'ImageCreate': 1657193869000, 'Tag': 'T1_8d9262_202207071937_156'},
                {'ImageCreate': 1657192465000, 'Tag': 'T1_8d9262_202207071913_155'},
                {'ImageCreate': 1657007910000, 'Tag': 'T1_21f396_202207051557_154'},
                {'ImageCreate': 1656993237000, 'Tag': 'T1_8cdc18_202207051153_153'},
                {'ImageCreate': 1656942166000, 'Tag': 'T1_adf36f_202207042141_152'},
                {'ImageCreate': 1656918371000, 'Tag': 'T1_99fbfd_202207041505_151'},
                {'ImageCreate': 1656660617000, 'Tag': 'T1_2144ec_202207011529_150'},
                {'ImageCreate': 1656654125000, 'Tag': 'T1_37ba8c_202207011341_149'},
                {'ImageCreate': 1656554703000, 'Tag': 'dev_20220629_orderPopup_a38e9c_202206301004_148'},
                {'ImageCreate': 1656504567000, 'Tag': 'T1_15de36_202206292008_147'},
                {'ImageCreate': 1656410314000, 'Tag': 'T1_63c4a4_202206281757_146'},
                {'ImageCreate': 1655897485000, 'Tag': 'T1_ce4293_202206221930_145'},
                {'ImageCreate': 1655891241000, 'Tag': 'T1_e971f4_202206221746_144'},
                {'ImageCreate': 1655886319000, 'Tag': 'T1_8f4e82_202206221624_142'},
                {'ImageCreate': 1655883351000, 'Tag': 'T1_b80a74_202206221535_141'},
                {'ImageCreate': 1655865581000, 'Tag': 'T1_da311f_202206221039_140'}]
        data = data[:limit]
    return data


def get_repotags_by_service(service_id, env_id):
    service = Service.objects.get(id=service_id)
    business = service.business

    lobenvsettingobj = LobEnvSetting.objects.filter(business_id=business.id, project_id=None, service_id=None, env_id=env_id).first()
    if not lobenvsettingobj:
        return []
    repoobj = lobenvsettingobj.repo
    repo_namespace = lobenvsettingobj.repo_namespace_src or lobenvsettingobj.repo_namespace
    return get_repotags(repo=repoobj, repo_namespace_name=repo_namespace, repo_name=service.code)


#### multi order
#### demandorder

def demandorder_deployment_ready_status(data):
    if data.get("generation", 1) == data.get("observed_generation") and data.get("ready_replicas", 100) == data.get(
            "replicas", 99) and data.get("unavailable_replicas", 99) is None:
        return True
    return False


def demandorder_deployment_status(demandorder):
    kube = get_demandorder_kube_and_namespace(demandorder)
    kubeid = str(kube.get('kubeid'))
    kubeconfig = kube.get('kubeconfig')
    namespace = kube.get('namespace')
    kubecli = KubeClient(kubeid, kubeconfig)
    status = True
    for workorder in demandorder.orders.filter(delete=0):
        service_name = workorder.service.code
        env_name = workorder.env.code
        deployment_name = service_name + '-deployment'
        ret = kubecli.get_deployment_status(deployment_name, namespace)
        set_deployment_info_cache(service_name, env_name, ret)
        if demandorder_deployment_ready_status(ret) == False:
            status = False
    return status


# def demandorder_repo_tag_ready(demandorder):
#     if not re.search('auto', demandorder.step.function):
#         return True, 'finish'
#     images = {}
#     lobobj = LobEnvSetting.objects.filter(business_id=demandorder.business_id, project_id__isnull=True, service_id__isnull=True,
#                                           env_id=demandorder.env_id).first()
#     if lobobj.repo_namespace_src == None or lobobj.repo_namespace_src == lobobj.repo_namespace:
#         return True, 'finish'
#     i = 0
#     for worder in demandorder.orders.filter(delete=0):
#         cur_workder_step = worder.steps.last()
#         if cur_workder_step.step != demandorder.step:
#             continue
#         i+=1
#         if cur_workder_step.status in ['wait', 'fail']:
#             src = lobobj.repo.url + '/' + lobobj.repo_namespace_src + '/' + worder.service.code + ':' + worder.version
#             dest = lobobj.repo.url + '/' + lobobj.repo_namespace + '/' + worder.service.code + ':' + worder.version
#             images[src] = dest
#     if len(images) != 0:
#         ish = ImageSyncHelper(lobobj.repo.url, lobobj.repo.username, lobobj.repo.password)
#         ret = ish.sync(images, workorder.id)
#         return ret, 'process'
#     if i != 0:
#         return True, 'process'
#     return True, 'finish'
    
    



# def demandorder_auto_do(demandorder, username):
#     if not re.search('auto', demandorder.step.function):
#         return 'finish'
#     process = 0
#     for worder in demandorder.orders.filter(delete=0):
#         cur_workder_step = worder.steps.last()
#         if cur_workder_step.step != demandorder.step:
#             continue
#
#         if cur_workder_step.comment:
#             print('comment:', cur_workder_step.comment)
#             res = workorder_auto_do_task.AsyncResult(cur_workder_step.comment)
#             print(res.status)
#             if res.status == 'SUCCESS' and res.get().get('step_status') == 'finish':
#                 print(res.get())
#                 continue
#             elif res.status == 'PENDING':
#                 process+=1
#                 continue
#
#
#
#         process+=1
#         ret = workorder_auto_do_task.delay(worder.id, cur_workder_step.step.function, username)
#         # print(ret)
#         cur_workder_step.comment = ret
#         cur_workder_step.save()
#     if process == 0:
#         next_step = demandorder.step.yes_step
#         demandorder.step_id = next_step.id
#         demandorder.save()
#         return 'finish'
#     else:
#         return 'process'




def workorder_yaml_format(workorder):
    appname = workorder.service.code
    yaml_template = get_workorder_template(workorder)
    if not yaml_template:
        return None
    lobsetting = workorder.setting
    namespace = lobsetting.namespace
    image = lobsetting.repo.url + '/' + lobsetting.repo_namespace + '/' + appname + ':' + workorder.version
    secret_name = lobsetting.repo_pull_secret
    params = {'namespace': namespace, 'appname': appname, 'replicas': 1, 'secret_name': secret_name, 'imagename': image, 'port': '8899'}
    yh = YamlHelper()
    yaml = yh.format_yaml_template(yaml_template, params)
    workorder.yaml = yaml
    workorder.save()
    return yaml


def workorder_auto_do(workorder, step_function, username):
    pass
    cur_workorder_step = workorder.steps.last()
    if cur_workorder_step.step.function != step_function:
        return 'finish'
    if cur_workorder_step.comment:
        res = workorder_auto_do_task.AsyncResult(cur_workorder_step.comment)
        if res.status == 'SUCCESS' and res.get().get('step_status') == 'finish':
            return 'finish'
        elif res.status == 'PENDING':
            return 'process'
    ret = workorder_auto_do_task.delay(workorder.id, cur_workorder_step.step.function, username)
    # print(ret)
    cur_workorder_step.comment = ret
    cur_workorder_step.save()
    return 'process'

def demandorder_auto_do(demandorder, username):
    if not re.search('auto', demandorder.step.function):
        return 'finish'
    process = 0
    for worder in demandorder.orders.filter(delete=0):
        cur_workder_step = worder.steps.last()
        if cur_workder_step.step != demandorder.step:
            continue

        if cur_workder_step.comment:
            res = workorder_auto_do_task.AsyncResult(cur_workder_step.comment)
            if res.status == 'SUCCESS' and res.get().get('step_status') == 'finish':
                continue
            elif res.status == 'PENDING':
                process+=1
                continue



        process+=1
        ret = workorder_auto_do_task.delay(worder.id, cur_workder_step.step.function, username)
        # print(ret)
        cur_workder_step.comment = ret
        cur_workder_step.save()
    if process == 0:
        next_step = demandorder.step.yes_step
        demandorder.step_id = next_step.id
        demandorder.save()
        return 'finish'
    else:
        return 'process'


def get_deployment_resources(service_id, env_id):
    service = Service.objects.get(id=service_id)
    env = Environment.objects.get(id=env_id)
    kube, namespace = get_kube_by_service_env(service, env)

    # kube = get_workorder_kube_and_namespace(workorder)
    if not kube:
        return ''
    kubeid = str(kube.id)
    kubeconfig = kube.kubeconfig

    service_name = service.name

    kubecli = KubeClient(kubeid, kubeconfig)

    resources = kubecli.get_deployment_resources(name=service_name+'-deployment', namespace=namespace)
    return {'resources': resources }